package com.moyun.syssecurity.filter;

import com.moyun.model.common.Constants;
import com.moyun.common.utils.SpringContextUtil;
import com.moyun.syssecurity.handler.MyAuthenticationFailureHandler;
import org.springframework.security.core.AuthenticationException;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * <h3>moyun-base</h3>
 * <p>专门用于校验验证码的过滤器</p>
 *
 * @author : ybx
 * @date : 2021-09-15 15:04:26
 **/
public class VerificationCodeFilter extends OncePerRequestFilter {


    // 自定义一个验证码校验失败的异常
    public class VerificationCodeException extends AuthenticationException {
        public VerificationCodeException() {
            super("图形验证码校验失败");
        }

    }

    // 实现自己的过滤器逻辑
    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain filterChain) throws ServletException, IOException {

        // 非登录请求不校验验证码, 直接放行
        if (!"/login".equals(req.getRequestURI())) {
            filterChain.doFilter(req, resp);
        } else {
            try {
                verificationCode(req);
                filterChain.doFilter(req, resp);
            } catch (VerificationCodeException e) {
                MyAuthenticationFailureHandler failureHandler = SpringContextUtil.getBean(MyAuthenticationFailureHandler.class);
                failureHandler.onAuthenticationFailure(req, resp, e);
            }

        }
    }

    /**
     * @return void
     * @Author yangboxuan
     * @Description 校验验证码
     * @Date 2021/9/15 15:19
     * @Param [req]
     **/
    private void verificationCode(HttpServletRequest req) throws VerificationCodeException {
        String reqCode = req.getParameter(Constants.CAPTCHA);
        HttpSession session = req.getSession();
        // 从session会话中, 取出 会话初次建立时绑定的 图片验证码
        String saveCode = (String) session.getAttribute(Constants.CAPTCHA);
        // 1. 随手清除验证码,无论是失败,还是成功. 客户端应在登陆失败时刷新验证码
        if (!StringUtils.isEmpty(saveCode)) {
            session.removeAttribute(Constants.CAPTCHA);
        }
        // 2. 校验不通过,抛出异常
        if (StringUtils.isEmpty(reqCode) || StringUtils.isEmpty(saveCode) || !reqCode.equals(saveCode)) {
            throw new VerificationCodeException();
        }


    }
}
